﻿///////////////////////////////////////////////////////////////////////////////
// File Name: SubClass.h
// Purpose: 
// Author: Paul DiLascia、张东斌、ChongyangLee
// Comment: 
// CSubClassWnd 类是从 CodeJock 库中提取出来的，并作了少量的更改
// 下面保留原有的信息
////////////////////////////////////////////////////////////////
// Copyright 1998 Paul DiLascia
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
/////////////////////////////////////////////////////////////////////////////
/****************************************************************************
 *
 * $Date: 10/26/99 10:50p $
 * $Revision: 4 $
 * $Archive: /CodeJock/Include/Subclass.h $
 *
 * $History: Subclass.h $
 * 
 * *****************  Version 4  *****************
 * User: Kirk Stowell Date: 10/26/99   Time: 10:50p
 * Updated in $/CodeJock/Include
 * Made class methods virtual for inheritance purposes.
 * 
 * *****************  Version 3  *****************
 * User: Kirk Stowell Date: 10/14/99   Time: 12:41p
 * Updated in $/CodeJock/Include
 * Added source control history to file header.
 *
 ***************************************************************************/
/////////////////////////////////////////////////////////////////////////////

//////////////////
// Generic class to hook messages on behalf of a CWnd.
// Once hooked, all messages go to CSubclassWnd::WindowProc before going
// to the window. Specific subclasses can trap messages and do something.
//
// To use:
//
// * Derive a class from CSubclassWnd.
//
// * Override CSubclassWnd::WindowProc to handle messages. Make sure you call
//   CSubclassWnd::WindowProc if you don't handle the message, or your
//   window will never get messages. If you write seperate message handlers,
//   you can call Default() to pass the message to the window.
//
// * Instantiate your derived class somewhere and call HookWindow(pWnd)
//   to hook your window, AFTER it has been created.
//	  To unhook, call HookWindow(NULL).
//
// This is a very important class, crucial to many of the widgets Window
// widgets implemented in PixieLib. To see how it works, look at the HOOK
// sample program.
//
///////////////////////////////////////////////////////////////////////////////



#ifndef _SUBCLASSW_H
#define _SUBCLASSW_H

#if _MSC_VER > 1000
#pragma once
#endif

class  SKINTKDLL CSubclassWnd : public CObject {
public:
	DECLARE_DYNAMIC(CSubclassWnd);
	CSubclassWnd();
	virtual ~CSubclassWnd();

	inline BOOL			GetAutoDestroy(){ return m_bAutoDestroy; }
	void			SetAutoDestroy(BOOL bAutoDestroy){m_bAutoDestroy = bAutoDestroy;}
	virtual BOOL	HookWindow(HWND  hwnd);
	virtual BOOL	HookWindow(CWnd* pWnd)	{ return HookWindow(pWnd->GetSafeHwnd()); }
	virtual BOOL	IsHooked() const		{ return m_hWnd!=NULL; }
	virtual BOOL	IsValidHook() const { return ::IsWindow(m_hWnd); }

	inline HWND			GetHwnd() const { return m_hWnd; }
	inline CWnd*			GetCWnd() const { return CWnd::FromHandle(m_hWnd); }

	#ifdef _WIN64
	inline LONG_PTR			GetExStyle() const
	{
		return ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
	}
#else
	inline LONG_PTR			GetExStyle() const
	{
		return ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
	}
#endif
#ifdef _WIN64
	inline LONG_PTR			GetStyle() const
	{
		return ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
	}
	#else
	inline LONG_PTR GetStyle() const
	{
		return ::GetWindowLong(m_hWnd, GWL_STYLE);
	}
	#endif
	inline HWND			GetParent() const { return ::GetParent(m_hWnd); }
	inline void			GetClientRect(LPRECT pRect) const { ::GetClientRect(m_hWnd, pRect); }
	inline void			GetWindowRect(LPRECT pRect) const { ::GetWindowRect(m_hWnd, pRect); }
	inline void			Invalidate(BOOL bErase = TRUE) const { ::InvalidateRect(m_hWnd, NULL, bErase); }
	inline BOOL			IsWindowEnabled() const { return ::IsWindowEnabled(m_hWnd); }
	inline BOOL			IsWindowVisible() const { return ::IsWindowVisible(m_hWnd); }

	void			ClientToWindow(LPRECT pRect);
	void			ScreenToClient(LPRECT pRect);
	void			ClientToScreen(LPRECT pRect);
	void			ClientToScreen(LPPOINT pPoint);
	LRESULT			Default(UINT msg,WPARAM wp, LPARAM lp);
	friend LRESULT CALLBACK HookWndProc(HWND, UINT, WPARAM, LPARAM);
	friend class CSubclassWndMap;

#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
	BOOL				m_bAutoDestroy;		// auto destroy 
	HWND				m_hWnd;				// the window hooked
	WNDPROC				m_pOldWndProc;		// ..and original window proc
	CSubclassWnd*		m_pNext;			// next in chain of hooks for this window

	virtual LRESULT WindowProc(UINT msg, WPARAM wp, LPARAM lp);
	virtual LRESULT Default();
	
};

class CSubclassWndMap : private CMapPtrToPtr {
public:
	CSubclassWndMap();
	~CSubclassWndMap();
	static CSubclassWndMap& GetHookMap();
	void Add(HWND hwnd, CSubclassWnd* pSubclassWnd);
	void Remove(CSubclassWnd* pSubclassWnd);
	void RemoveAll(HWND hwnd);
	CSubclassWnd* Lookup(HWND hwnd);
};

#define	theHookMap	(CSubclassWndMap::GetHookMap())


#endif

